home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Super Models
/
Hot Super Models.iso
/
unix
/
x11
/
xv200.tar
/
xv-2.00
/
xvpopup.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-02
|
11KB
|
425 lines
/*
* xvpopup.c - popup "Are you sure? Yes/No/Maybe" sort of dialog box
*
* callable functions:
*
* CenterMapWindow(win,x,y) - maps and centers a window around the mouse
* PopUp(str,...) - maps, sets up popW
* OpenAlert(str) - maps a button-less window
* CloseAlert() - closes a button-less window
* PUCheckEvent(event) - called by event handler
* TextRect() - draws semi-complex strings in a rectangle
*/
/*
* Copyright 1989, 1990, 1991, 1992 by John Bradley and
* The University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any expressed or implied warranty.
*
* The author may be contacted via:
* US Mail: John Bradley
* GRASP Lab, Room 301C
* 3401 Walnut St.
* Philadelphia, PA 19104
*
* Phone: (215) 898-8813
* EMail: bradley@cis.upenn.edu
*/
#include "xv.h"
#include "bitmaps.h"
#define PUWIDE 400
#define PUHIGH 170
#define BUTTH 24
#ifdef __STDC__
static void createPUD(void);
static void drawPUD(int, int, int, int);
static void clickPUD(int, int);
#else
static void createPUD(), drawPUD(), clickPUD();
#endif
/* local variables */
Window popW;
int nbts, selected, popUp=0, firsttime=1;
BUTT *bts;
char *text;
char accel[8];
/***************************************************/
void CenterMapWindow(win, dx, dy, w, h)
Window win;
int dx, dy, w, h;
{
XSizeHints hints;
Window rW,cW;
int rx,ry,x,y,wx,wy;
unsigned int mask;
if (!XQueryPointer(theDisp,rootW,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
/* couldn't query mouse. just center on screen */
wx = (dispWIDE-w)/2; wy = (dispHIGH-h)/2;
}
else {
wx = x - dx;
wy = y - dy;
if (wx<0) wx = 0;
if (wy<0) wy = 0;
if (wx + w > dispWIDE) wx = dispWIDE - w;
if (wy + h > dispHIGH) wy = dispHIGH - h;
}
wx -= (p_offx + ch_offx);
wy -= (p_offy + ch_offy);
if (!XGetNormalHints(theDisp, win, &hints)) hints.flags = 0;
hints.width = hints.min_width = hints.max_width = w;
hints.height = hints.min_height = hints.max_height = h;
hints.x = wx; hints.y = wy;
hints.flags |= (USSize | PMinSize | PMaxSize | USPosition);
XSetNormalHints(theDisp, win, &hints);
XMoveWindow(theDisp, win, wx, wy);
XMapRaised(theDisp, win);
}
/***************************************************/
int PopUp(txt, labels, n)
char *txt, *labels[];
int n;
{
int i;
XEvent event;
if (firsttime) createPUD();
XStoreName(theDisp, popW, "xv confirm");
XSetIconName(theDisp, popW, "xv confirm");
bts = (BUTT *) malloc(n * sizeof(BUTT));
if (!bts) FatalError("unable to malloc buttons in popup\n");
nbts = n;
selected = 0;
text = txt;
for (i=0; i<n; i++) {
BTCreate(&bts[i], popW, PUWIDE - (n-i) * (80 + 10), PUHIGH - 10 - BUTTH,
80, BUTTH, labels[i]+1, infofg, infobg);
accel[i] = labels[i][0];
}
/* center last button in window around mouse position, with constraint that
window be fully on the screen */
CenterMapWindow(popW, 40 + bts[nbts-1].x, BUTTH/2 + bts[nbts-1].y,
PUWIDE, PUHIGH);
popUp = 1;
/* MUST wait for VisibilityNotify event to come in, else we run the risk
of UnMapping the window *before* the Map request completed. This
appears to be bad, (It leaves an empty window frame up.) though it
generally only happens on slow servers. Better safe than screwed... */
XWindowEvent(theDisp, popW, VisibilityChangeMask, &event);
/* block until this window gets closed */
while (popUp) {
XNextEvent(theDisp, &event);
HandleEvent(&event, &i);
}
/* free stuff */
XUnmapWindow(theDisp, popW);
free(bts);
return(selected);
}
/***************************************************/
void OpenAlert(txt)
char *txt;
{
/* pops up a window with txt displayed in it (*no buttons*).
returns immediately. window is close by 'CloseAlert()'.
No 'PopUp()' calls are allowed while an Alert is displayed. */
int i;
XEvent event;
if (firsttime) createPUD();
XStoreName(theDisp, popW, "xv notice");
XSetIconName(theDisp, popW, "xv notice");
nbts = 0;
selected = 0;
text = txt;
/* center last button in window around mouse position, with constraint that
window be fully on the screen */
CenterMapWindow(popW, PUWIDE/2, PUHIGH/2, PUWIDE, PUHIGH);
popUp = 1;
/* MUST wait for VisibilityNotify event to come in, else we run the risk
of UnMapping the window *before* the Map request completed. This
appears to be bad, (It leaves an empty window frame up.) though it
generally only happens on slow servers. Better safe than screwed... */
XWindowEvent(theDisp, popW, VisibilityChangeMask, &event);
drawPUD(0, 0, PUWIDE, PUHIGH);
XFlush(theDisp);
}
/***************************************************/
void CloseAlert()
{
popUp = 0;
XUnmapWindow(theDisp, popW);
}
/***************************************************/
int PUCheckEvent(xev)
XEvent *xev;
{
/* check event to see if it's for us. If so, return 1, otherwise 0 */
int rv = 0;
if (!popUp) return(0);
if (xev->type == Expose) {
XExposeEvent *e = (XExposeEvent *) xev;
if (e->window == popW) {
drawPUD(e->x, e->y, e->width, e->height);
rv = 1;
}
}
else if (xev->type == ButtonPress) {
XButtonEvent *e = (XButtonEvent *) xev;
if (e->button == Button1 && e->window == popW) {
clickPUD(e->x,e->y);
rv = 1;
}
}
else if (xev->type == KeyPress) {
XKeyEvent *e = (XKeyEvent *) xev;
char buf[128]; KeySym ks; XComposeStatus status;
int stlen, i;
stlen = XLookupString(e,buf,128,&ks,&status);
buf[stlen] = '\0';
/* note: we accept keyboard accellerators in *any* window */
if (stlen) {
if (buf[0] == '\r') buf[0] = '\n';
/* search for character in accel table */
for (i=0; i<nbts; i++) {
if (buf[0] == accel[i] && buf[0] != ' ') {
FakeButtonPress(&bts[i]);
rv = 1;
}
}
if (!rv && buf[0]=='\033' && nbts==1) { /* ESC accepted in 1-but pu's */
FakeButtonPress(&bts[0]);
rv = 1;
}
}
else rv = 1; /* 'accept' non-char strings (ie, shift or ctrl press) */
}
else if (xev->type == ClientMessage) {
Atom proto, delwin;
XClientMessageEvent *client_event = (XClientMessageEvent *) xev;
proto = XInternAtom(theDisp, "WM_PROTOCOLS", FALSE);
delwin = XInternAtom(theDisp, "WM_DELETE_WINDOW", FALSE);
if (client_event->message_type == proto &&
client_event->data.l[0] == delwin) {
/* it's a WM_DELETE_WINDOW event */
if (client_event->window == popW) {
FakeButtonPress(&bts[(nbts>1) ? nbts-1 : 0]);
rv = 1;
}
}
}
if (rv==0 && (xev->type == KeyPress || xev->type == ButtonPress)) {
XBell(theDisp, 0);
rv = 1; /* eat it */
}
return rv;
}
#define TR_MAXLN 10
/***************************************************/
void TextRect(win, txt, x, y, w, h, fg)
Window win;
char *txt;
int x,y,w,h;
u_long fg;
{
char *sp, *ep, *oldep, *start[TR_MAXLN];
int i, inbreak, lineno, top, hardcr, maxln, len[TR_MAXLN];
XSetForeground(theDisp, theGC, fg);
sp = txt; lineno = hardcr = 0;
maxln = h / LINEHIGH;
RANGE(maxln,0,TR_MAXLN);
while (*sp && lineno<maxln) {
/* drop off any leading spaces (except on first line or after \n) */
if (sp!=txt && !hardcr) {
while(*sp==' ') sp++;
}
hardcr = 0; ep = sp;
/* increment ep until we A) get too wide, B) hit eos or
C) hit a '\n' character */
/* NOTE: ep points to the character AFTER the end of the line */
while (XTextWidth(mfinfo, sp, ep-sp) <= w && *ep && *ep!='\n') ep++;
if (*ep=='\n') { ep++; hardcr=1; } /* eat newline */
/* if we got too wide, back off until we find a break position
(last char before a space or a '/') */
if (XTextWidth(mfinfo, sp, ep-sp) > w) {
oldep = ep; inbreak = 0;
while (ep!=sp) {
ep--;
if ( inbreak && *ep!=' ') { ep++; break; }
if (!inbreak && *ep==' ') inbreak = 1;
if (*ep=='/') { ep++; break; }
}
if (ep==sp) ep = oldep-1; /* can't break this line. oh well */
}
start[lineno] = sp; len[lineno] = ep-sp;
/* make sure we don't print a trailing '\n' character! */
if (len[lineno] > 0) {
while (sp[len[lineno]-1] == '\n') len[lineno] = len[lineno] - 1;
}
sp = ep;
lineno++;
}
top = y + h/2 + (ASCENT-DESCENT)/2 - ((lineno-1)*LINEHIGH)/2;
if (top<y+ASCENT) top = y+ASCENT;
for (i=0, y=top; i<lineno; i++, y+=LINEHIGH) {
if (start[i][0] != '\n')
XDrawString(theDisp, win, theGC, x, y, start[i], len[i]);
}
}
/***************************************************/
static void createPUD()
{
CARD32 data[2];
Atom prop;
popW = CreateWindow("xv confirm", "+0+0", PUWIDE, PUHIGH, infofg, infobg);
if (!popW) FatalError("can't create popup window!");
data[0] = (CARD32) XInternAtom(theDisp, "WM_DELETE_WINDOW", FALSE);
data[1] = (CARD32) time((long *)0);
prop = XInternAtom(theDisp, "WM_PROTOCOLS", FALSE),
XChangeProperty(theDisp, popW, prop, prop,
32, PropModeReplace, (unsigned char *) data, 2);
XSelectInput(theDisp, popW, ExposureMask | ButtonPressMask | KeyPressMask
| VisibilityChangeMask);
XSetTransientForHint(theDisp, popW, mainW);
bts = (BUTT *) NULL;
nbts = selected = firsttime = 0;
}
/***************************************************/
static void drawPUD(x,y,w,h)
int x,y,w,h;
{
int i,xt,yt;
XRectangle xr;
xr.x = x; xr.y = y; xr.width = w; xr.height = h;
XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
XSetForeground(theDisp, theGC, infofg);
XSetBackground(theDisp, theGC, infobg);
XCopyPlane(theDisp, iconPix, popW, theGC, 0,0, icon_width, icon_height,
10,10+(PUHIGH-30-BUTTH-icon_height)/2,1);
xt = 10+icon_width+20; yt = 10;
TextRect(popW, text, xt, yt, PUWIDE-10-xt, PUHIGH-10-BUTTH-20, infofg);
for (i=0; i<nbts; i++) BTRedraw(&bts[i]);
XSetClipMask(theDisp, theGC, None);
}
/***************************************************/
static void clickPUD(x,y)
int x,y;
{
int i,j;
BUTT *bp;
for (i=0; i<nbts; i++) {
bp = &bts[i];
if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
}
if (i<nbts && BTTrack(bp)) {
popUp = 0; selected = i;
}
}